package com.housekeeping.controller.api;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.housekeeping.model.Order;
import com.housekeeping.model.User;
import com.housekeeping.service.OrderService;
import com.housekeeping.service.impl.OrderServiceImpl;
import com.housekeeping.utils.ApiResponse;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 订单管理模块控制器
 */
@WebServlet("/api/orders/*")
public class OrderApiController extends HttpServlet {
    
    private OrderService orderService = new OrderServiceImpl();
    private ObjectMapper objectMapper = new ObjectMapper();
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        
        String pathInfo = req.getPathInfo();
        
        try {
            if (pathInfo == null || pathInfo.equals("/")) {
                handleGetAllOrders(req, resp);
            } else if (pathInfo.matches("/\\d+")) {
                handleGetOrderById(req, resp);
            } else if (pathInfo.equals("/user")) {
                handleGetUserOrders(req, resp);
            } else {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(404, "Not Found"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(500, "Internal Error"));
        }
    }
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        
        try {
            handleCreateOrder(req, resp);
        } catch (Exception e) {
            e.printStackTrace();
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(500, "Internal Error"));
        }
    }

    @Override
    protected void doPut(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        
        String pathInfo = req.getPathInfo();
        
        try {
            if (pathInfo != null && pathInfo.matches("/\\d+/status")) {
                handleUpdateOrderStatus(req, resp);
            } else if (pathInfo != null && pathInfo.matches("/\\d+")) {
                handleUpdateOrder(req, resp);
            } else {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(404, "Not Found"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(500, "Internal Error"));
        }
    }
    
    private void handleGetAllOrders(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        
        String statusParam = req.getParameter("status");
        List<Order> orders;
        
        if (statusParam != null) {
            int status = Integer.parseInt(statusParam);
            orders = orderService.getAllOrdersWithDetails().stream()
                .filter(order -> order.getStatus() == status)
                .collect(java.util.stream.Collectors.toList());
        } else {
            orders = orderService.getAllOrdersWithDetails();
        }
        
        ApiResponse.sendJsonResponse(req, resp, ApiResponse.success(orders));
    }
    
    private void handleGetOrderById(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        
        String pathInfo = req.getPathInfo();
        int orderId = Integer.parseInt(pathInfo.substring(1));
        
        Order order = orderService.getOrderById(orderId);
        if (order != null) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.success(order));
        } else {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(404, "Order not found"));
        }
    }
    
    private void handleGetUserOrders(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        
        HttpSession session = req.getSession(false);
        if (session == null) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(401, "Not logged in"));
            return;
        }
        
        User currentUser = (User) session.getAttribute("user");
        if (currentUser == null) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(401, "Not logged in"));
            return;
        }
        
        List<Order> orders = orderService.getOrdersByUserId(currentUser.getUserId());
        ApiResponse.sendJsonResponse(req, resp, ApiResponse.success(orders));
    }
    
    private void handleCreateOrder(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        
        HttpSession session = req.getSession(false);
        if (session == null) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(401, "Not logged in"));
            return;
        }
        
        User currentUser = (User) session.getAttribute("user");
        if (currentUser == null) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(401, "Not logged in"));
            return;
        }
        
        try {
            String requestBody = req.getReader().lines()
                .reduce("", (accumulator, actual) -> accumulator + actual);
            
            Map<String, Object> orderData = objectMapper.readValue(
                requestBody, new TypeReference<Map<String, Object>>() {});
            
            Order order = new Order();
            order.setUserId(currentUser.getUserId());
            order.setServiceId((Integer) orderData.get("serviceId"));
            

            if (orderData.get("serviceTime") != null) {
                String serviceTimeStr = (String) orderData.get("serviceTime");

                java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
                order.setServiceDate(sdf.parse(serviceTimeStr));
            }
            
            order.setAddress((String) orderData.get("address"));
            order.setPhone((String) orderData.get("phone"));
            order.setRemark((String) orderData.get("requirements"));
            order.setStatus(1);
            order.setCreateTime(new Date());
            
            if (orderService.createOrder(order)) {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.success("Order created successfully"));
            } else {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(400, "Failed to create order"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(400, "Invalid request data"));
        }
    }

    private void handleUpdateOrderStatus(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        
        String pathInfo = req.getPathInfo();
        int orderId = Integer.parseInt(pathInfo.substring(1, pathInfo.indexOf("/status")));
        
        HttpSession session = req.getSession(false);
        if (session == null) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(401, "Not logged in"));
            return;
        }
        
        User currentUser = (User) session.getAttribute("user");
        if (currentUser == null) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(401, "Not logged in"));
            return;
        }
        
        try {
            String requestBody = req.getReader().lines()
                .reduce("", (accumulator, actual) -> accumulator + actual);
            
            Map<String, Object> statusData = objectMapper.readValue(
                requestBody, new TypeReference<Map<String, Object>>() {});
            
            Order order = orderService.getOrderById(orderId);
            if (order == null) {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(404, "Order not found"));
                return;
            }
            
            Integer newStatus = (Integer) statusData.get("status");
            if (newStatus == null) {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(400, "Status is required"));
                return;
            }
            

            if (currentUser.getUserType() != 1 && currentUser.getUserId() != order.getUserId()) {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(403, "Permission denied"));
                return;
            }
            
            order.setStatus(newStatus);
            if (orderService.updateOrder(order)) {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.success("Order status updated successfully"));
            } else {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(400, "Failed to update order status"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(400, "Invalid request data"));
        }
    }

    private void handleUpdateOrder(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        
        String pathInfo = req.getPathInfo();
        int orderId = Integer.parseInt(pathInfo.substring(1));
        
        HttpSession session = req.getSession(false);
        if (session == null) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(401, "Not logged in"));
            return;
        }
        
        User currentUser = (User) session.getAttribute("user");
        if (currentUser == null) {
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(401, "Not logged in"));
            return;
        }
        
        try {
            String requestBody = req.getReader().lines()
                .reduce("", (accumulator, actual) -> accumulator + actual);
            
            Map<String, Object> orderData = objectMapper.readValue(
                requestBody, new TypeReference<Map<String, Object>>() {});
            
            Order order = orderService.getOrderById(orderId);
            if (order == null) {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(404, "Order not found"));
                return;
            }
            

            if (currentUser.getUserType() != 1 && currentUser.getUserId() != order.getUserId()) {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(403, "Permission denied"));
                return;
            }
            

            if (orderData.get("address") != null) {
                order.setAddress((String) orderData.get("address"));
            }
            if (orderData.get("phone") != null) {
                order.setPhone((String) orderData.get("phone"));
            }
            if (orderData.get("requirements") != null) {
                order.setRemark((String) orderData.get("requirements"));
            }
            if (orderData.get("serviceTime") != null) {
                String serviceTimeStr = (String) orderData.get("serviceTime");
                java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
                order.setServiceDate(sdf.parse(serviceTimeStr));
            }
            
            if (orderService.updateOrder(order)) {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.success("Order updated successfully"));
            } else {
                ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(400, "Failed to update order"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            ApiResponse.sendJsonResponse(req, resp, ApiResponse.error(400, "Invalid request data"));
        }
    }
} 